package com.cy.dda.service.comm.impl;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.OSSObject;
import com.cy.dda.comm.constant.Constants;
import com.cy.dda.model.dto.comm.OSSFileDownloadDTO;
import com.cy.dda.service.BaseService;
import com.cy.dda.service.comm.FileDownloadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.List;
import java.util.zip.Adler32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Description OSS 文件下载service
 * @Author tanyilin
 * @Date 2019/6/6 10:22
 */
@Slf4j
@Service
public class OssFileDownloadServiceImpl extends BaseService implements FileDownloadService {

    @Autowired
    private OSSClient ossClient;

    @Override
    public void download(String ossKey, BufferedOutputStream bos) {

        BufferedInputStream bis = null;
        try {
            //从oss进行下载文件
            OSSObject ossObject = ossClient.getObject(Constants.BUCKETNAME, ossKey);
            //得到缓冲文件输入流
            bis = new BufferedInputStream(ossObject.getObjectContent());
            //输出
            byte[] b = new byte[1024];
            int L;
            while ((L = bis.read(b)) != -1) {
                if(b.length != 0) {
                    bos.write(b, 0, L);
                }
            }

        } catch (IOException e) {
            log.error("download file error", e);
        }finally {
            try {
                //释放、关闭输出流
                if(bos != null) {
                    bos.flush();
                    bos.close();
                }
                //关闭输入流
                if(bis != null) {
                    bis.close();
                }
            } catch (IOException e) {
                log.error("关闭、释放输入输出流异常", e);
            }

        }

    }

    @Override
    public void downloadFilesForZip(List<OSSFileDownloadDTO> list, BufferedOutputStream bos) {

        try {
            //创建临时zip文件
            File zipTempFile = File.createTempFile("temp", ".zip");
            FileOutputStream fos = new FileOutputStream(zipTempFile);
            //作用是为任何OutputStream产生校验和
            //第一个参数是制定产生校验和的输出流，第二个参数是指定Checksum的类型 （Adler32（较快）和CRC32两种）
            CheckedOutputStream cos = new CheckedOutputStream(fos, new Adler32());
            //用于将数据压缩成Zip文件格式
            ZipOutputStream zos = new ZipOutputStream(cos);
            for(OSSFileDownloadDTO bean : list) {
                String ossKey = bean.getOssKey();
                //从oss进行下载文件
                OSSObject ossObject = ossClient.getObject(Constants.BUCKETNAME, ossKey);
                //读取Object内容得到输入流
                InputStream inputStream = ossObject.getObjectContent();
                //对于每一个要被存放到压缩包的文件，都必须调用ZipOutputStream对象的putNextEntry()方法，确保压缩包里面文件不同名
                String suffix = ossKey.substring(ossKey.lastIndexOf("."));
                String fileName = bean.getFileName().concat(suffix);
                zos.putNextEntry(new ZipEntry(fileName));
                int L;
                //向压缩文件中输出数据
                while ((L = inputStream.read()) != -1) {
                    zos.write(L);
                }
                inputStream.close();
                //当前文件写完，定位为写入下一条项目
                zos.closeEntry();
            }
            //循环压缩完之后，关闭压缩文件输出流
            zos.close();

            //将临时的压缩文件输出到客户端
            FileInputStream fis = new FileInputStream(zipTempFile);
            //得到缓冲文件输入流
            BufferedInputStream bis = new BufferedInputStream(fis);
            byte[] b = new byte[1024];
            int L;
            while ((L = bis.read(b)) != -1) {
                bos.write(b, 0, L);
            }
            //关闭流
            bos.flush();
            bos.close();
            bis.close();
            fis.close();
            //删除临时zip文件
            zipTempFile.delete();

        } catch (IOException e) {
            log.info("downloadFilesForZip error", e);
        }

    }


}
